package com.gitee.wsl.android.ui.recyclerView.adapter

import android.annotation.SuppressLint
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.VIEW_HOLDER_TYPE_EMPTY
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.EmptyViewHolder
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.Subscriber
import com.gitee.wsl.android.ui.recyclerView.animation.AdapterAnimationHelper
import com.gitee.wsl.android.ui.recyclerView.callback.OnViewAttachStateChangeListener
import com.gitee.wsl.android.ui.recyclerView.callback.ViewAttachStateChangeListenerContainer
import com.gitee.wsl.ext.base.isTrue
import com.gitee.wsl.ext.base.trueValue
import java.lang.ref.WeakReference

open class ListWarpBuilderAdapter<T:Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>(private val listAdapter: ListAdapter<T,RecyclerView.ViewHolder>,
                                                                                                               adapterConfig: AdapterConfig<T,AR>) : BaseBuilderAdapter<T,AR>(listAdapter,adapterConfig) {

    override fun getItem(position: Int): T? {
        return listAdapter.currentList[position]
    }

    fun submitList(list: MutableList<T>?){
        submitList(list,null)
    }

    fun submitList(list: MutableList<T>?, commitCallback: Runnable?) {
        listAdapter.submitList(list?.let { tranList(it) },commitCallback)
    }

    private fun tranList(list: List<T>):List<T>{
        val filter=adapterConfig.filterHandler
        val sorter=adapterConfig.sortHandler
        val filterList= filter?.let { list.filter { filter(it) } }?:list
        return sorter?.let{filterList.sortedWith(sorter)}?:filterList
    }
}

open class ListBuilderAdapter<T:Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>(
                                protected val adapterConfig: AdapterConfig<T,AR>
) : ListAdapter<T, RecyclerView.ViewHolder>(adapterConfig.diffCallback),LayoutChangeSet ,
    com.gitee.wsl.android.ui.recyclerView.adapter.SelectHelperScope<T>,
    ViewAttachStateChangeListenerContainer {

    protected val defaultViewHolderFactoryCache=adapterConfig.viewHolderFactoryCache

    var layoutType:Int = AdapterConfig.LAYOUT_TYPE_DEFAULT

    var selectHelper: com.gitee.wsl.android.ui.recyclerView.adapter.SampleSelectHelper<T>? =
        adapterConfig.hasFlag(AdapterConfig.FLAG_SELECT_ABLE or AdapterConfig.FLAG_MULTI_SELECT_ABLE).
        trueValue(
            com.gitee.wsl.android.ui.recyclerView.adapter.SampleSelectHelper(
                this,
                adapterConfig.hasFlag(AdapterConfig.FLAG_MULTI_SELECT_ABLE)
            )
        )

    init {
        val repository=getRepository()
        if(repository!=null && adapterConfig.repository==null)
            adapterConfig.repository=repository
        if(selectHelper!=null && adapterConfig.selectHelper==null)
            adapterConfig.selectHelper=selectHelper
        selectHelper?.let {
            this.registerAdapterDataObserver(it)
        }
        adapterConfig.itemFlagManger?.apply {
            init { getItem( it) }
            registerAdapterDataObserver(observer)
        }

    }

    override fun submitList(list: MutableList<T>?){
        submitList(list,null)
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun submitList(list: MutableList<T>?, commitCallback: Runnable?) {
        super.submitList(list?.let { tranList(it) },commitCallback)
        this.notifyDataSetChanged()
    }

    private fun tranList(list: List<T>):List<T>{
        val filter=adapterConfig.filterHandler
        val sorter=adapterConfig.sortHandler
        val filterList= filter?.let { list.filter { filter(it) } }?:list
        return sorter?.let{filterList.sortedWith(sorter)}?:filterList
    }

    private val sparseArrayLayoutInflater = SparseArray<WeakReference<LayoutInflater>>(1)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        if(viewType== VIEW_HOLDER_TYPE_EMPTY) return EmptyViewHolder(parent)
        return defaultViewHolderFactoryCache[viewType].getViewHolder(
            parent, sparseArrayLayoutInflater.get(0).get() ?: LayoutInflater.from(parent.context)
        )
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        onBindViewHolder(holder, position, emptyList())
    }

    override fun onBindViewHolder(
        holder: RecyclerView.ViewHolder,
        position: Int,
        payloads: List<Any>
    ) {
        if (position != RecyclerView.NO_POSITION) {
            if (holder is Subscriber<*,*>) {
                holder as Subscriber<T,AR>
                holder.onBindViewHolder(position, payloads, getItem(position),adapterConfig )
            }
        }
    }

    fun getRepository(): AR?=null

    override fun getItemViewType(position: Int): Int {
        var pre:T?=null
        var next:T?=null
        (position>0).isTrue { pre=getItem(position-1) }
        (position<itemCount).isTrue { next=getItem(position+1) }
        return adapterConfig.itemTypeCallBack?.let { it(position,getItem(position),pre,next,layoutType) }?: VIEW_HOLDER_TYPE_EMPTY
    }

    override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
        if (holder is Subscriber<*,*>) {
            holder.unBindViewHolder(holder.absoluteAdapterPosition)
        }
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        sparseArrayLayoutInflater.append(0, WeakReference(LayoutInflater.from(recyclerView.context)))
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        defaultViewHolderFactoryCache.clear()
        sparseArrayLayoutInflater.clear()
    }

    override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
        if (holder is Subscriber<*,*>) {
            holder.onViewAttachedToWindow(holder, holder.absoluteAdapterPosition)
        }
        mOnViewAttachStateChangeListeners.forEach {
            it.onViewAttachedToWindow(holder)
        }
    }

    override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
        if (holder is Subscriber<*,*>) {
            holder.onViewDetachedFromWindow(holder, holder.absoluteAdapterPosition)
        }
        mOnViewAttachStateChangeListeners.forEach {
            it.onViewDetachedFromWindow(holder)
        }
    }

    override fun layoutChange(layoutType: Int) {
        this.layoutType=layoutType
    }

    var animatorAdapter: AdapterAnimationHelper?=null

    fun ableAnimation(animatorAdapter: AdapterAnimationHelper = AdapterAnimationHelper()){
        addOnViewAttachStateChangeListener(animatorAdapter)
    }

    fun disableAnimation(){
        animatorAdapter?.let {
            removeOnViewAttachStateChangeListener(it)
        }
        animatorAdapter = null
    }

    private val mOnViewAttachStateChangeListeners: MutableList<OnViewAttachStateChangeListener> by lazy {
        mutableListOf()
    }

    override fun addOnViewAttachStateChangeListener(listener: OnViewAttachStateChangeListener) {
        mOnViewAttachStateChangeListeners.add(listener)
    }

    override fun removeOnViewAttachStateChangeListener(listener: OnViewAttachStateChangeListener) {
        mOnViewAttachStateChangeListeners.remove(listener)
    }

}


class EmptyListAdapter<T:Any>( diffCallback:DiffUtil.ItemCallback<T>): ListAdapter<T, RecyclerView.ViewHolder>(diffCallback){
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RecyclerView.ViewHolder {
        return EmptyViewHolder(parent)
    }
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {}
}